<?php

/* 
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
namespace Admin\Model;
use Think\Model;
use Org\Util\Rest;
/**
 * 同步的模型
 */
class SyncModel extends Model{
    
    protected $tablePrefix = 'gr_';
   
    protected $leancloudName;

    //映射的字段
   protected $_map = array('objectId' => 'id','createdAt'=>'createdate', 'updatedAt'=>'lastupdate'); 
    
    /**
     * 数据关联的表
     * {
     *      "__type": "Pointer",
     *      "className": "GameScore",
     *      "objectId": "51e3a6b5e4b0169469540546"
     * }
     * @var type 
     */
    protected $pointer = array();
    
    /**
     * 多对多
     * {
     *      "__type": "Relation",
     *      "className": "GameScore",
     * }
     * @var type 
     */
    protected $relation = array();
    
    /**
     * leancloud 字段类型配置
     * @var type 
     */
    protected $leancloudelds = array();
    
    public function field() {
        $this->options['field']   =   implode(',',$this->getDbFields());
        return $this;
    }
    
    protected function _after_select(&$resultSet, $options){
        foreach ($resultSet as &$result) {
            $this->_after_find($result, $options);
        }
    }
    
    protected function _after_find(&$result, $options)
    {
        foreach ($result as $field => $value) {
            $this->_parseType($result, $field);
        }
    }
    
    
    protected function _facade(&$data) {
        foreach ($data as $key=>$val){
            //字段映射
            if($this->_map[$key])
                $data[$this->_map[$key]] = $val;
            
            if(!in_array($key,$this->getDbFields())){
                unset($data[$key]);
            }elseif(is_scalar($val)) {
                // 字段类型检查 和 强制转换
                $this->_parseType($data,$key);
            }
        }
        return $data;
    }
    
    /**
     * 字段类型转换
     * @param type $list
     * @return array
     */
    protected function filterFields($list){
        $results = array();
        foreach ($list as $result) {
            foreach ($result as $field => $value) {
                if($field == "createdAt" || $field == "updatedAt"){
                    unset($result[$field]);
                    continue;
                }
                $this->_parseType($result, $field);
                if($this->leancloudelds[$field] == "String"){
                    if (!is_string($value))
                        $result[$field] = $value.'';
                }else if($this->leancloudelds[$field] == "Pointer"){
                    $this->pointer[$field]["objectId"] = $value;
                    $result[$field] = $this->pointer[$field];
                }else if($this->leancloudelds[$field] == "Date"){
                    $micro = sprintf("%03d",($t - floor($t)) * 1000);
                    $result[$field] = array("__type"=>"Date","iso"=> date('Y-m-d',$value).'T'.date('H:i:s',$value).'.'.$micro.'Z');
                }else if($this->leancloudelds[$field] == "Relation")
                    $result[$field] = $this->relation[$field];
                else if($this->leancloudelds[$field] == "Bytes")
                    $result[$field] = array("__type"=>"Bytes","base64"=>  base64_decode ($value));   
            }
            array_push($results, $result);
        }
        //dump($results);
        return $results;
    }


    public function push(){
        //需要同步数据数量
        $count = $this->where("syncStatus<>0")->count();
        //分批执行
        $size = 10;
        $page = (int)($count/$size); 
        if(($count%$size) > 0)
            $page ++; 
        $ids = array();
        $error = array();
        for ($i=0; $i<$page; $i++){
            $start = $i*$size;
            //查询数据
            $list = $this->where("syncStatus<>0")->limit($start,$size)->select();
            
           
            //同步leancloud
            $rest = new Rest();
            //批量处理
            $results = $rest->batch(array('className' => $this->leancloudName, 'results' => $this->filterFields($list)));
            if($results->code == 200)
                foreach ($results->body as $result){
                    if($result->success){
                        if($result->success->objectId)
                            array_push($ids, $result->success->objectId);
                    }else
                        array_push($error, $result->error);
                }
            else
                continue;
            }
        $where = array();
        //同步更新
        if(count($ids) > 0)
            array_push($where, array('id'=>array('in',$ids)));
        if(((int)$count)-count($ids)-count($error) > 0){
            $where['syncStatus'] = 3;
            $where['_logic'] = 'OR';
        }
        if(count($where) > 0)
            $this->where($where)->setField('syncStatus',0);
            
        $message = array('count'=>$count,'syncCount'=>count($ids));
        if(count($error) > 0)
            array_merge($message, array('error'=>$error));
        return $message;
    }
    
    public function pull(){
        $cql = urlencode('select count(*) from '.$this->leancloudName.' where syncStatus<>0');
        $rest = new Rest();
        //获取数据总数
        $result = $rest->query('cql='.$cql);
        if($result->body->count){
            $count = $result->body->count;
            $page = (int)($count/10); 
            if(($count%10) > 0)
                $page ++; 
            for ($i=0; $i<$page; $i++){
                $start = $i*10;
                $end = $start + 10;
                //查询数据
                $cql = urlencode('select * from '.$this->leancloudName.' where syncStatus<>0 limit '.$start.','.$end);
                $result = $rest->query('cql='.$cql);
                
                if($result->body->results){
                    $data = array();
                    $results = $result->body->results;
                    foreach ($results as $o){
                        $params=array('objectId'=> $o->objectId,'syncStatus'=>2);
                        $syncStatus = $o->syncStatus;
                        $o->syncStatus=0;
                        if($syncStatus == 1)
                            $this->add((array)$o);
                        else{
                            if($syncStatus == 3){
                                $o->status=-1;
                                $params['syncStatus'] = 3;
                            }
                            $this->save((array)$o);
                        }
                        array_push($data, $params);
                    }
                    if(count($data) > 0)
                        $results = $rest->batch(array('className' => $this->leancloudName, 'results' => $data));
                }
            }
        }
        return array('code'=>0);
    }
}